import { debounce } from "lodash";
import {
  InsertTextOperation,
  DeleteTextOperation,
  SetSelectionOperation,
} from "../operations";

class UndoAndRedoList {
  // 撤销操作二维数组
  undoList_ = [];
  // 还原操作二维数组
  redoList_ = [];
  curPos_ = -1;
  opts = [];
  maxCapacity = 100; // 最大栈容量
  constructor(editor) {
    this.editor = editor;
  }
  // 监测是否光标操作
  checkIsAllSelectionOp() {
    const curOp = this.undoList_[this.undoList_.length - 1];
    if (curOp === null || curOp === void 0) {
      return false;
    }
    let isAllSelectionOp = curOp.every(
      (opItem) => opItem.type === "SetSelectionOpt"
    );
    // 全清空
    if (isAllSelectionOp) {
      this.curPos_ = this.undoList_.length - 1;
      this.undoList_.pop();
    }
  }

  addOperation(op) {
    // 做光标合并
    const debounce_ = debounce(() => {
      this.checkIsAllSelectionOp();
      if (this.opts && this.opts.length) {
        const filterOps = this.filterRepeatSelection(this.opts);
        const undos = this.mergeOpt(filterOps);
        // 不要让空操作加进undo
        if (undos.length) {
          // 栈超出上限删除操作
          this.undoList_.push(undos);
          // 设置当前下标
          this.curPos_ = this.undoList_.length - 1;
        }
      }

      this.opts = [];
    }, 300);
    // 超过栈容量，移除最前
    if (this.undoList_.length >= this.maxUndoCount) {
      this.undoList_.shift();
    }
    this.opts.push(op);
    debounce_();
  }
  // 过滤重复选区操作或者空
  filterRepeatSelection(ops) {
    const filterOp = [];
    for (let op of ops) {
      if (op.type === "SetSelectionOpt") {
        const preOp = filterOp.at(-1);
        if (!preOp || preOp.type === "SetSelectionOpt") continue;
      }

      filterOp.push(op);
    }
    return filterOp;
  }
  // 触发所有操作的合并方法
  mergeOpt(ops) {
    const finalUndos = [];
    for (let op of ops) {
      const normalOp = finalUndos.at(-2);
      const selectionOp = finalUndos.at(-1);
      // 合并插入/删除操作
      if (
        normalOp instanceof InsertTextOperation &&
        op instanceof InsertTextOperation
      ) {
        const newInsertOp = op.merge(normalOp);
        finalUndos[finalUndos.length - 2] = newInsertOp;
        continue;
      }
      // 合并相邻选区（取最后一次)
      if (
        selectionOp instanceof SetSelectionOperation &&
        op instanceof SetSelectionOperation
      ) {
        const newSelectionOp = op.merge(selectionOp);
        finalUndos[finalUndos.length - 1] = newSelectionOp;
        continue;
      }
      finalUndos.push(op);
    }
    return finalUndos;
  }

  // 还原
  redoOperation(apply) {
    if (this.redoList_.length) {
      const redo = this.redoList_.at(-1);
      redo.forEach((item) => apply(item));
      this.redoList_.pop();
      this.undoList_.push(redo);
    }
  }
  // 撤销
  undoOperation(apply) {
    if (this.undoList_.length) {
      const undo = this.undoList_.at(-1);
      if (undo) {
        for (let i = undo.length - 1; i >= 0; i--) {
          console.log(undo[i]);
          console.log(undo[i].reverse());

          apply(undo[i].reverse());
        }
        this.undoList_.pop();
        this.redoList_.push(undo);
      }
    }
  }
}

export default function history(editor) {
  const apply = editor.apply.bind(editor);
  const undoAndRedoList = new UndoAndRedoList(editor);
  editor.apply = (op) => {
    if (!op) return;

    undoAndRedoList.addOperation(op);
    apply(op);
  };
  editor.undo = () => {
    undoAndRedoList.undoOperation(apply);
  };
  editor.redo = () => {
    undoAndRedoList.redoOperation(apply);
  };
  return editor;
  // const undos = [];
  // const redos = [];
  // const addHistory = debounce((operations) => {}, 100);
  // editor.apply = (op) => {
  //   const operations = [];
  //   apply(op);
  //   addHistory(operations);
  // };
  // editor.undo = () => {
  //   const last = undos.pop();
  //   const reverseOps = last.map((op) => {
  //     return op.reverse();
  //   });
  // };
}
